import type { CSSProperties, Ref, SetupContext } from 'vue'
import { computed, nextTick, getCurrentInstance, reactive } from 'vue'
import { VTableProps, VtableEmits } from './vtableProps'
import { VTableRef } from './table'
import { isArray } from '@vue/shared'
import { Column } from 'element-plus'
import { cloneDeep } from 'lodash-es'

export const useTable = (props: VTableProps, targetRef: VTableRef) => {
  const instance = getCurrentInstance()!
  const emits = instance.emit as SetupContext<VtableEmits>['emit']

  // 展示列数据源
  const vaildColumn = computed(() => props.columns.filter((it: any) => !it.hidden))

  const state = reactive({
    tableData: props.data || props.modelValue,
  })

  // 分组线判断标识字段groupProp
  // const cellClassGroup = ({ row, column, rowIndex, columnIndex }) => {
  //   if (props.isGroup) {
  //     if (column.property == props.groupProp) {
  //       const tabelData = instance.proxy?.data
  //       const pre = tabelData[rowIndex - 1]
  //       const next = tabelData[rowIndex + 1]
  //       return `${judge(row, pre, next)} v-group`
  //     }
  //   }
  // }

  // 分组线——————start

  // 分组线判断标识字段groupProp
  const cellClassGroup = ({
    row,
    column,
    rowIndex,
    columnIndex,
  }: {
    row: any
    column: any
    rowIndex: number
    columnIndex: number
  }) => {
    if (props.isGroup) {
      if (column.property == props.groupProp) {
        return `${row.groupFlag} v-group`
      }
    }
  }

  const formatData = (data: any = [], pageNum: any, pageSize: any) => {
    if (!data.length) return []
    // 当前页开始条数
    const pageSizeAll = pageSize * (pageNum - 1)

    // 上一页最后一条
    let pgUp = pageNum == 1 ? '' : data.find((val: any, index: number) => index == pageSizeAll - 1) || ''
    // 下一页的第一条
    const pgDnFirstNum = pageSize * pageNum //索引
    let pgDn = pgDnFirstNum + 1 <= data.length ? data.find((val: any, index: number) => index == pgDnFirstNum) || '' : ''

    // 当前页面显示内容
    const rightData = data.slice(pageSizeAll, pageSizeAll + pageSize)
    // 加样式
    const all = pageSizeAll + pageSize
    for (let index = pageSizeAll; index < all; index++) {
      const it = data[index]
      if (!it) return
      const next = rightData.length == index + 1 ? pgDn : rightData[index + 1]
      const pre = index == 0 ? pgUp : rightData[index - 1]
      it.groupFlag = judge(it, pre, next)
    }
  }

  const judge = (cur: any, pre: any = {}, next: any = {}) => {
    if (!props.groupMark) return
    if (!cur[props.groupMark] || cur[props.groupMark] == '0') return ''
    if (cur[props.groupMark] != pre[props.groupMark] && cur[props.groupMark] != next[props.groupMark]) return ''
    if (!pre || cur[props.groupMark] != pre[props.groupMark]) return 'v-line-start'
    if (!next || cur[props.groupMark] != next[props.groupMark]) return 'v-line-stop'
    return 'v-line-center'
  }
  // 分组线—————— end

  // 开启表格编辑模式，组件全键盘操作
  const enterJumptoNext = (event: any, row: any, column: Column, $index: number) => {
    // const enterJumptoNext = ({ event, row, column, $index }: { event: KeyboardEvent; row: any; column: any; $index: number }) => {
    if (event.key === 'Enter') {
      Object.keys(row).forEach((key) => {
        if (key === `${column.property}focus`) row[key] = false
      })

      // 如果为空则禁止跳转
      if (!row[column.property]) return

      let index = vaildColumn.value.findIndex((it: any) => it.prop === column.property) + 1

      let next = vaildColumn.value[index]

      if (!next && $index == state.tableData.length - 1) return
      let nextVal: any = next || vaildColumn.value[0]
      const rowVal = next ? row : state.tableData[$index + 1]
      let indexVal = next ? index : 0

      //  当遇见禁用的跳过禁用选项跳转到下一个
      while (rowVal[nextVal.prop + 'disabled'] || (!nextVal.subassembly && indexVal < vaildColumn.value.length - 1)) {
        nextVal = vaildColumn.value[++indexVal]
      }
      if (!nextVal.prop) return
      rowVal[nextVal.prop + 'focus'] = true

      // 聚焦后 将指令值都设置为false
      nextTick(() => {
        delete rowVal[nextVal.prop + 'focus']
      })
      // 当遇见禁用的跳过禁用选项跳转到下一个
      // while (row[next.prop + 'disabled'] || (!next.subassembly && index < vaildColumn.value.length - 1)) {
      //   next = vaildColumn.value[++index]
      // }

      // if (!next.prop) return
      // row[next.prop + 'focus'] = true

      // // 聚焦后 将指令值都设置为false
      // nextTick(() => {
      //   delete row[next.prop + 'focus']
      // })
    }
  }

  // 父组件事件处理，新增行数据参数
  const getEventHandlers = (eventList: any, row: any, column: any, $index: number) => {
    const handlers: Record<string, Function | null> = {}

    // 键盘操作默认添加
    if (props.iskeyboard) {
      handlers.keyup = function (...eventArgs: string[]) {
        enterJumptoNext(...eventArgs, row, column, $index)
      }
    }

    for (const event in eventList) {
      handlers[event] = function (...eventArgs: any) {
        if (props.iskeyboard && event === 'keyup') {
          Object.keys(row).forEach((key) => {
            if (key.includes('focus')) row[key] = false
          })
          console.warn('你已重写了当前表格键盘操作，默认键盘操作已失效')
        }
        eventList[event] && eventList[event](...eventArgs, row, column, $index)
      }
    }
    return handlers
  }

  // 是否每行设置单独行验证
  const isRequired = (column: any, row: any) => {
    let required = column.subOptions?.required || !!column.subOptions?.rules?.length
    const key = column.prop + 'required'

    if (row[key]) required = row[key] ?? required
    return required
  }

  // 是否设置单独行验证规则
  const formattRules = (column: any, row: any) => {
    let rules = column.subOptions?.rules || [{ required: true, trigger: ['change', 'blur'], message: `${column.label}不能为空` }]

    const key = column.prop + 'rules'
    if (row[key]) rules = row[key]

    return rules
  }

  /**
   * @param column
   * @param row
   * @returns 返回组件参数
   */
  const formattSubOptions = (column: any, row: any) => {
    const prop = column.prop
    // 深拷贝 subOptions 中的组件参数以防止组件的参数重复使用一个
    const obj = cloneDeep(column.subOptions)

    if (typeof obj === 'object' && !isArray(obj)) {
      for (let key in obj) {
        // 将 column 列上的参数和 row 行上的参数合并
        if (row[prop + key]) {
          // 当字段值为对象时合并
          /**
           * 为数组和字段、字段从新赋值
           */
          if (isArray(row[prop + key])) {
            obj[key] = row[prop + key]
          } else if (typeof row[prop + key] === 'object') {
            Object.assign(obj[key], row[prop + key])
          } else {
            obj[key] = row[prop + key]
          }
        }
      }
    }
    return obj
  }

  // 修改
  const modify = (scope: any) => {
    emits('modify', scope)
  }

  // 保存
  const save = (scope: any) => {
    emits('save', scope)
  }

  // 删除
  const remove = (scope: any) => {
    emits('remove', scope)
  }

  return {
    vaildColumn,
    formatData,
    isRequired,
    formattRules,
    formattSubOptions,
    getEventHandlers,
    modify,
    save,
    remove,
    cellClassGroup,
    state,
  }
}
